`include"mycpu.h"
module mycpu_top(
    input aclk,
    input aresetn,
    //read acquire
    output [ 3:0] arid, //inst: 0, data: 1
    output [31:0] araddr,
    output [ 7:0] arlen, //set to 0
    output [ 2:0] arsize,
    output [ 1:0] arburst, //set to 2'b01
    output [ 1:0] arlock, //set to 0
    output [ 3:0] arcache, //set to 0
    output [ 2:0] arprot,
    output        arvalid,
    input         arready,
    //read
    input  [ 3:0] rid, //inst: 0, data: 1
    input  [31:0] rdata,
    input  [ 1:0] rresp, //ignored
    input         rlast, //ignored
    input         rvalid,
    output         rready,
    //write acquire
    output [ 3:0] awid,
    output [31:0] awaddr,
    output [ 7:0] awlen,
    output [ 2:0] awsize,
    output [ 1:0] awburst, //set to 2'b01
    output [ 1:0] awlock, //set to 0
    output [ 3:0] awcache, //set to 0
    output [ 2:0] awprot, //set to 0
    output        awvalid,
    input         awready,
    //write data
    output [ 3:0] wid, //set to 1
    output [31:0] wdata,
    output [ 3:0] wstrb,
    output        wlast, //set to 1
    output        wvalid,
    input         wready,
    //write feedback
    input  [ 3:0] bid, //ignored
    input  [ 1:0] bresp, //ignored
    input         bvalid,
    output        bready,
    // trace debug interface
    output wire [31:0] debug_wb_pc,
    output wire [ 3:0] debug_wb_rf_we,
    output wire [ 4:0] debug_wb_rf_wnum,
    output wire [31:0] debug_wb_rf_wdata
);
/******************** DECLARATION ********************/
    //cpu data
    wire cpu_data_req;
    wire cpu_data_wr;
    wire [1:0] cpu_data_size;
    wire [31:0] cpu_data_addr;
    wire [3:0] cpu_data_wstrb;
    wire [31:0] cpu_data_wdata;
    wire cpu_data_addr_ok;
    wire cpu_data_data_ok;
    wire [31:0] cpu_data_rdata;
    //cpu inst
    wire cpu_inst_req;
    wire cpu_inst_wr;
    wire [1:0] cpu_inst_size;
    wire [31:0] cpu_inst_addr;
    wire [3:0] cpu_inst_wstrb;
    wire [31:0] cpu_inst_wdata;
    wire cpu_inst_addr_ok;
    wire cpu_inst_data_ok;
    wire [31:0] cpu_inst_rdata;
    //i-cache
    wire icache_rd_req;
    wire [2:0] icache_rd_type;
    wire [31:0] icache_rd_addr;
    wire icache_rd_rdy;
    wire icache_ret_valid;
    wire icache_ret_last;
    wire [31:0] icache_ret_data;
    wire icache_wr_req;
    wire [2:0] icache_wr_type;
    wire [31:0] icache_wr_addr;
    wire [3:0] icache_wr_wstrb;
    wire [127:0] icache_wr_data;
    wire icache_wr_rdy;
    wire icache_mtype;
    //d-cache
    wire dcache_rd_req;
    wire [2:0] dcache_rd_type;
    wire [31:0] dcache_rd_addr;
    wire dcache_rd_rdy;
    wire dcache_ret_valid;
    wire dcache_ret_last;
    wire [31:0] dcache_ret_data;
    wire dcache_wr_req;
    wire [2:0] dcache_wr_type;
    wire [31:0] dcache_wr_addr;
    wire [3:0] dcache_wr_wstrb;
    wire [127:0] dcache_wr_data;
    wire dcache_wr_rdy;
    wire dcache_mtype;
/******************** CPU CORE ********************/
    mycpu_core u_mycpu_core(
        .clk(aclk),
        .resetn(aresetn),
        //inst sram
        .inst_sram_req(cpu_inst_req),
        .inst_sram_wr(cpu_inst_wr),
        .inst_sram_size(cpu_inst_size),
        .inst_sram_addr(cpu_inst_addr),
        .inst_sram_wstrb(cpu_inst_wstrb),
        .inst_sram_wdata(cpu_inst_wdata),
        .inst_sram_addr_ok(cpu_inst_addr_ok),
        .inst_sram_data_ok(cpu_inst_data_ok),
        .inst_sram_rdata(cpu_inst_rdata),
        //data sram
        .data_sram_req(cpu_data_req),
        .data_sram_wr(cpu_data_wr),
        .data_sram_size(cpu_data_size),
        .data_sram_addr(cpu_data_addr),
        .data_sram_wstrb(cpu_data_wstrb),
        .data_sram_wdata(cpu_data_wdata),
        .data_sram_addr_ok(cpu_data_addr_ok),
        .data_sram_data_ok(cpu_data_data_ok),
        .data_sram_rdata(cpu_data_rdata),
        //debug
        .debug_wb_pc(debug_wb_pc),
        .debug_wb_rf_we(debug_wb_rf_we),
        .debug_wb_rf_wnum(debug_wb_rf_wnum),
        .debug_wb_rf_wdata(debug_wb_rf_wdata),
        //mtype
        .i_mtype(icache_mtype),
        .d_mtype(dcache_mtype)
    );
/******************** I-CACHE ********************/
    cache u_icache(
        .clk(aclk),
        .resetn(aresetn),
        .valid(cpu_inst_req),
        .mtype(icache_mtype),
        .op(cpu_inst_wr),
        .index(cpu_inst_addr[11:4]),
        .tag(cpu_inst_addr[31:12]),
        .offset(cpu_inst_addr[3:0]),
        .wstrb(cpu_inst_wstrb),
        .wdata(cpu_inst_wdata),
        .addr_ok(cpu_inst_addr_ok),
        .data_ok(cpu_inst_data_ok),
        .rdata(cpu_inst_rdata),
        //AXI read
        .rd_req(icache_rd_req),
        .rd_type(icache_rd_type),
        .rd_addr(icache_rd_addr),
        .rd_rdy(icache_rd_rdy),
        .ret_valid(icache_ret_valid),
        .ret_last(icache_ret_last),
        .ret_data(icache_ret_data),
        //AXI write
        .wr_req(icache_wr_req),
        .wr_type(icache_wr_type),
        .wr_addr(icache_wr_addr),
        .wr_wstrb(icache_wr_wstrb),
        .wr_data(icache_wr_data),
        .wr_rdy(icache_wr_rdy)
    );
/******************** D-CACHE ********************/
    cache u_dcache(
        .clk(aclk),
        .resetn(aresetn),
        .valid(cpu_data_req),
        .mtype(dcache_mtype),
        .op(cpu_data_wr),
        .index(cpu_data_addr[11:4]),
        .tag(cpu_data_addr[31:12]),
        .offset(cpu_data_addr[3:0]),
        .wstrb(cpu_data_wstrb),
        .wdata(cpu_data_wdata),
        .addr_ok(cpu_data_addr_ok),
        .data_ok(cpu_data_data_ok),
        .rdata(cpu_data_rdata),
        //AXI read
        .rd_req(dcache_rd_req),
        .rd_type(dcache_rd_type),
        .rd_addr(dcache_rd_addr),
        .rd_rdy(dcache_rd_rdy),
        .ret_valid(dcache_ret_valid),
        .ret_last(dcache_ret_last),
        .ret_data(dcache_ret_data),
        //AXI write
        .wr_req(dcache_wr_req),
        .wr_type(dcache_wr_type),
        .wr_addr(dcache_wr_addr),
        .wr_wstrb(dcache_wr_wstrb),
        .wr_data(dcache_wr_data),
        .wr_rdy(dcache_wr_rdy)
    );
/******************** AXI BRIDGE ********************/
    axi_bridge u_axi_bridge(
        .clk(aclk),
        .resetn(aresetn),
        /* cache-AXI interface */
        //inst cache read
        .i_rd_req(icache_rd_req),
        .i_rd_type(icache_rd_type),
        .i_rd_addr(icache_rd_addr),
        .i_rd_rdy(icache_rd_rdy),
        .i_ret_valid(icache_ret_valid),
        .i_ret_last(icache_ret_last),
        .i_ret_data(icache_ret_data),
        //inst cache write
        .i_wr_req(1'b0),
        .i_wr_type(icache_wr_type),
        .i_wr_addr(icache_wr_addr),
        .i_wr_wstrb(icache_wr_wstrb),
        .i_wr_data(icache_wr_data),
        .i_wr_rdy(icache_wr_rdy),
        //data cache read
        .d_rd_req(dcache_rd_req),
        .d_rd_type(dcache_rd_type),
        .d_rd_addr(dcache_rd_addr),
        .d_rd_rdy(dcache_rd_rdy),
        .d_ret_valid(dcache_ret_valid),
        .d_ret_last(dcache_ret_last),
        .d_ret_data(dcache_ret_data),
        //data cache write
        .d_wr_req(dcache_wr_req),
        .d_wr_type(dcache_wr_type),
        .d_wr_addr(dcache_wr_addr),
        .d_wr_wstrb(dcache_wr_wstrb),
        .d_wr_data(dcache_wr_data),
        .d_wr_rdy(dcache_wr_rdy),
        /* axi interface */
        //read acquire
        .arid(arid),
        .araddr(araddr),
        .arlen(arlen),
        .arsize(arsize),
        .arburst(arburst),
        .arlock(arlock),
        .arcache(arcache),
        .arprot(arprot),
        .arvalid(arvalid),
        .arready(arready),
        //read
        .rid(rid),
        .rdata(rdata),
        .rresp(rresp),
        .rlast(rlast),
        .rvalid(rvalid),
        .rready(rready),
        //write acquire
        .awid(awid),
        .awaddr(awaddr),
        .awlen(awlen),
        .awsize(awsize),
        .awburst(awburst),
        .awlock(awlock),
        .awcache(awcache),
        .awprot(awprot),
        .awvalid(awvalid),
        .awready(awready),
        //write
        .wid(wid),
        .wdata(wdata),
        .wstrb(wstrb),
        .wlast(wlast),
        .wvalid(wvalid),
        .wready(wready),
        //write feedback
        .bid(bid),
        .bresp(bresp),
        .bvalid(bvalid),
        .bready(bready)
    );

endmodule